'use strict';

const Service = require('egg').Service;
const crypto = require('crypto');
const md5 = require("js-md5");
const fs = require('fs-extra');
const path = require('path');
const {
    encMe,
    uncMe
} = require("../libs/crypto2DES");

class UnitsService extends Service {

    deleteUserFolderRecursive(type, fileName) {
        /**
        * 判断给定的路径是否存在
        */
        console.log(this.config.baseDir, 'app/public/' + type + "/" + fileName);
        const filePath = path.join(this.config.baseDir, 'app/public/' + type + "/" + fileName);
        console.log(filePath);
        if (fs.existsSync(filePath)) {
            fs.unlinkSync(filePath);
        } else {
            console.log(filePath + "  not exists");
        }
    };
    /**
     * 生成 Token
     * @param {Object} data  用户信息存储通常是{ id: user.id }
     */
    createToken(data) {
        return this.app.jwt.sign(data, this.app.config.jwt.secret, {
            expiresIn: "72h"
        });
    };

    /**
     * 验证token的合法性
     * @param {String} token
     */
    verifyToken(token) {
        let result = {};
        this.app.jwt.verify(token, this.app.config.jwt.secret, function (err, decoded) {
            if (err) {
                /*
                  err = {
                    name: 'TokenExpiredError',
                    message: 'jwt expired',
                    expiredAt: 1408621000
                  }
                */
                result.verify = false;
                result.message = err.message;
            } else {
                result.verify = true;
                result.message = decoded;
            }
        });
        return result;
    };

    /**
     * 创建Diffie-Hellman算法对应的secretkey
     */
    createDiffieHellmanForClient() {
        let cryptoObj = crypto.createDiffieHellman(512); //创建服务端dh对象
        let generateKey = cryptoObj.generateKeys(); //回传给客户端进行获取解析获取共同私钥
        let prime = cryptoObj.getPrime(); //同上
        let generator = cryptoObj.getGenerator(); //同上

        let generateKeyStr = generateKey.toString('base64').replace(/\+/g, '|');
        let primeStr = prime.toString('base64').replace(/\+/g, '|');
        let generatorStr = generator.toString('base64').replace(/\+/g, '|');
        this.app.listCryptoObj.push({
            key: md5(generateKeyStr),
            value: cryptoObj
        })
        return {
            generateKey: generateKeyStr,
            prime: primeStr,
            generator: generatorStr
        }
    };

    /**
     * 解析获取客户客户端与服务端对应的secret key
     * @param {*} generateKey 客户端传递的对应公开key generateKeys()
     * @param {*} publicKey 服务端给客户端传递的公钥 md5加密数据
     */
    computeSecret(generateKey, publicKey) {
        let cryptoObj = {};
        for (let item of this.app.listCryptoObj) {
            if (item.key === publicKey) {
                cryptoObj = item;
                break;
            }
        }
        if ($.isEmptyObject(cryptoObj)) {
            return "";
        }
        generateKey = generateKey.replace(/\|/g, '+');
        let keyBuffer = Buffer.from(generateKey, 'base64');
        let secretkey = cryptoObj.computeSecret(keyBuffer).toString('base64');
        return md5(secretkey);
    };

    connectUserFiled(_string) {

        let _SplitString = _string.split(",");
        let whereObj = '';
        let _length =_SplitString.length;
        for (let i = 0; i < _length; i++) {
            if (i ==  _length - 1) {
                whereObj += `us.user_id = '${_SplitString[i]}'  `;
            } else {
                whereObj += `us.user_id = '${_SplitString[i]}' OR `;
            }
        }
        console.log(whereObj)
        return whereObj;

    }

    /**
     * 服务端解析客户端对应的私钥信息数据 
     * @param {*} prime  客户端传递的 getPrime() 对应base64字符串
     * @param {*} generator 客户端传递的 getGenerator() 对应base64字符串
     * @param {*} generateKey 客户端传递的 generateKeys() 对应base64字符串
     */
    computeSecretForService(prime, generator, generateKey) {
        prime = prime.replace(/\|/g, '+');
        generator = generator.replace(/\|/g, '+');
        generateKey = generateKey.replace(/\|/g, '+');

        let primeBuffer = Buffer.from(prime, 'base64');
        let generatorBuffer = Buffer.from(generator, 'base64');
        let generateKeyBuffer = Buffer.from(generateKey, 'base64');

        let cryptoObj = crypto.createDiffieHellman(primeBuffer, generatorBuffer);
        let returnGenerateKey = cryptoObj.generateKeys();
        returnGenerateKey = returnGenerateKey.toString('base64').replace(/\+/g, '|');
        let secretkey = cryptoObj.computeSecret(generateKeyBuffer).toString('base64');
        return {
            generateKey: returnGenerateKey,
            secretkey: md5(secretkey)
        };
    };

    /**
     * 解密对应的加密字符串
     * @param {*} dataStr 待解密字符串
     * @param {*} key 密钥(32位)
     */
    decryptAES(dataStr, key) {
        let iv = key.substring(0, 16); // iv 向量(16位)
        let cipherChunks = [];
        let decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
        decipher.setAutoPadding(true);
        cipherChunks.push(decipher.update(dataStr, 'base64', 'utf8'));
        cipherChunks.push(decipher.final('utf8'));
        return cipherChunks.join('');
    };

    /**
     * 加密对应的字符串
     * @param {*} dataStr 待加密字符串
     * @param {*} key 密钥(32位)
     */
    encryptAES(dataStr, key) {
        let iv = key.substring(0, 16); // iv 向量(16位)
        let cipherChunks = [];
        let cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
        cipher.setAutoPadding(true);
        cipherChunks.push(cipher.update(dataStr, 'utf8', 'base64'));
        cipherChunks.push(cipher.final('base64'));
        return cipherChunks.join('');
    };

    /**
     * 移除内存缓存的CryptoObj对象数据
     * @param {*} key key值
     */
    removeDiffieHellman(key) {
        let tempIndex = -1;
        this.app.listCryptoObj.map((item, index) => {
            if (item.key === key) {
                tempIndex = index;
                return false;
            }
        })
        if (tempIndex !== -1)
            this.app.listCryptoObj.splice(tempIndex, 1);
    };

    /**
     * 解密对应的加密字符串
     * @param {*} dataStr 待解密字符串
     * @param {*} key 密钥
     */
    decryptDES(dataStr, key) {
        if (key === "-1") {
            return dataStr;
        } else {
            let secretkeyObj = this.createIVKey(key);
            if (secretkeyObj.code === 0) return null;
            return uncMe(dataStr, secretkeyObj.secretkey);
        }
    };

    /**
    * 解密对应的加密字符串
    * @param {*} dataStr 待解密字符串
    * @param {*} key 密钥
    */
    decryptDES2(dataStr, key) {
        return uncMe(dataStr, key);
    };

    /**
     * 加密对应的字符串
     * @param {*} dataStr 待加密字符串
     * @param {*} key 密钥
     */
    encryptDES2(dataStr, key) {
        return encMe(dataStr, key);
    };

    /**
     * 加密对应的字符串
     * @param {*} dataStr 待加密字符串
     */
     encryptDES(dataStr) {
        let secretkeyObj = this.createIVKey();
        let result = {};
        if (dataStr.length > 6000) {
            result = {
                data: dataStr,
                publicKey: '-1'
            }
        } else {
            result = {
                data: encMe(dataStr, secretkeyObj.secretkey),
                publicKey: secretkeyObj.publicKey
            }
        }
        return result;
    };
    /**
     * 获取秘钥生成或还原秘钥
     * @param {*} key 待还原秘钥字符串，为空代表创建
     */
    createIVKey(key = "") {
        if (key.length > 0) {
            if (key.indexOf('$') === -1) {
                return {
                    code: 0,
                    msg:  this.ctx.__('IllegalOp') 
                }
            }
            let tempKey = key.split('$')[0];
            let secretkey = key.split('$')[1];
            if (secretkey.indexOf(',') === -1) {
                return {
                    code: 0,
                    msg:  this.ctx.__('IllegalOp') 
                }
            }
            let listRandom = secretkey.split(',');
            let secretkeyStr = "";
            listRandom.forEach(k => {
                secretkeyStr += tempKey[parseInt(k)];
            })
            if (secretkeyStr.length !== 6) {
                return {
                    code: 0,
                    msg:  this.ctx.__('IllegalOp') 
                }
            }
            return {
                code: 1,
                secretkey: secretkeyStr
            }
        } else {
            let secretkey = this.ctx.helper.getGuid16();
            //随机产生6位随机数字，用于字符互调
            let listRandom = [];
            while (listRandom.length < 6) {
                let r = Math.random() * 16 | 0
                if (listRandom.indexOf(r) === -1) {
                    listRandom.push(r);
                }
            }
            let tempKey = "";
            listRandom.forEach(k => {
                tempKey += secretkey[k];
            })
            let intStr = listRandom.join(',');
            return {
                code: 1,
                secretkey: tempKey,
                publicKey: secretkey + "$" + intStr
            }
        }
    }

    /**
     * 短信发送
     * @param {*} phone 手机号码
     * @param {*} msgType 消息类型
     * 0 登录验证[SMS_184220690]
     * 1 密码重置[SMS_184215651]
     * 2 注册验证[SMS_184630700]
     * 3 用户账号绑定手机号码[SMS_184621009]
     */
    async sendCode(phone, msgType) {
        let returnData = {};
        // if (!this.ctx.helper.checkCellphone(phone)) {
        //     returnData = {
        //         code: 0,
        //         msg: '您输入的手机号码不合法,请您重新输入!!'
        //     }
        //     return returnData;
        // }
        // if (phone.length < 11 || phone.length > 13) {
        //     returnData = {
        //         code: 0,
        //         msg:  this.ctx.__('checkPNError')
        //     }
        //     return returnData;
        // }
        let templateCode = "";
        switch (msgType) {
            case 0://登录验证
                templateCode = "SMS_205060377";
                break;
            case 1://密码重置
                templateCode = "SMS_205060377";
                break;
            case 2://注册验证
                templateCode = "SMS_205060377";
                break;
            case 3://用户账号绑定手机号码
                templateCode = "SMS_205060377";
                break;
            case 4://用户手机解绑操作
                templateCode = "SMS_205060377";
                break;
        }
        //缓存中查询该手机号相关信息数据
        const listSendTime = await this.ctx.model.SmsSendRecord.findAll({
            attributes: ['SendTime', 'ID'],
            where: {
                Tel: phone,
                TemplateCode: templateCode
            },
            order: [
                ['SendTime', 'DESC']
            ],
            limit: 20
        })

        if (listSendTime != null && listSendTime != undefined && listSendTime.length > 0) {
            //同一类型二分钟内只能发送1条
            let lastDate = this.ctx.helper.dateAdd('m', 2, new Date(listSendTime[0].SendTime));
            lastDate = this.ctx.helper.dateAdd('h', 8 , new Date(lastDate));
	    let currentDate = this.ctx.helper.dateAdd('h', 7 , new Date());
	    currentDate = this.ctx.helper.dateAdd('m', -30 , currentDate );
            //console.log(currentDate)
            //console.log(lastDate)
	    if (currentDate <= lastDate) {
                returnData = {
                    code: 0,
                    msg:  this.ctx.__('phoneError1')  
                }
                return returnData;
            }

            //同一类型一小时内同一个号码只能发送5条
            let oldDate = this.ctx.helper.dateAdd('h', -1, new Date());
            let listTempSendTime1 = listSendTime.filter(x => {
                let time = new Date(x.SendTime);
                if (time >= oldDate && time <= currentDate)
                    return x;
            })
            if (listTempSendTime1 != null && listTempSendTime1 != undefined && listTempSendTime1.length >= 5) {
                returnData = {
                    code: 0,
                    msg: this.ctx.__('phoneError2')   
                }
                return returnData;
            }
            //同一类型一天内只能发送20条短信
            let time24 = new Date(`${currentDate.getFullYear()}/${currentDate.getMonth() + 1}/${currentDate.getDate()} 23:59:59`);
            let time00 = new Date(`${currentDate.getFullYear()}/${currentDate.getMonth() + 1}/${currentDate.getDate()} 00:00:00`);
            let listTempSendTime2 = listSendTime.filter(x => {
                let time = new Date(x.SendTime);
                if (time >= time00 && time <= time24)
                    return x;
            })
            if (listTempSendTime2 != null && listTempSendTime2 != undefined && listTempSendTime2.length >= 5) {
                returnData = {
                    code: 0,
                    msg:this.ctx.__('phoneError3')    
                }
                return returnData;
            }
        }
        //生成随机六位验证码
        let randomCode = "";
        for (var i = 0; i < 6; i++) {
            randomCode += Math.floor(Math.random() * 10);
        }

        // 调试环境 不请求阿里服务器
        if (!this.app.config.aliSMS.isopen) {
            returnData = await this.devCode(phone, randomCode, listSendTime, templateCode, msgType);
            console.log(returnData);
            return returnData;
        }
        //请求阿里云API发送验证码
        const ret = await this.service.alisms.sendSMS(phone, randomCode, templateCode, true, `{\"name\":'users',\"code\":${randomCode}}`);

        if (ret.Code === "OK") {
            // 数据库数据插入
            let transaction;
            try {
                // 建立事务对象
                transaction = await this.ctx.model.transaction();
                let smsSendRecordItem = {
                    ID: this.ctx.helper.getRandomNumber(9),
                    RequestId: ret.RequestId,
                    BizId: ret.BizId,
                    ResultCode: ret.Code,
                    SendContent: randomCode,
                    TemplateCode: templateCode,
                    Tel: phone,
                    SendTime: new Date(),
                    MsgType: msgType,
                    IsEffect: true
                }
                if (listSendTime != null && listSendTime != undefined && listSendTime.length > 0) {
                    await this.ctx.model.SmsSendRecord.update({
                        IsEffect: false
                    }, {
                        where: {
                            ID: listSendTime[0].ID
                        },
                        transaction
                    });
                }
                await this.ctx.model.SmsSendRecord.create(smsSendRecordItem, {
                    transaction
                });

                // 提交事务
                await transaction.commit();

                returnData = {
                    code: 1,
                    msg: this.ctx.__('sendCodeOk')   
                }
            } catch (err) {
                console.log(err)
                await transaction.rollback();// 事务回滚
                returnData = {
                    code: 3,
                    msg: this.ctx.__('sendCodeError')  
                }
            }
        } else {
            returnData = {
                code: 3,
                msg:  this.ctx.__('sendCodeError')  
            }
        }
        return returnData;
    }

    /**
     * 短信验证码验证
     * @param {*} phone 手机号码
     * @param {*} msgType 消息类型
     * 0 登录验证[SMS_184220690]
     * 1 密码重置[SMS_184215651]
     * 2 注册验证[SMS_184630700]
     * 3 用户账号绑定手机号码[SMS_184621009]
     * @param {*} msgCode 验证码
     */
    async checkMsgCode(phone, msgType, msgCode) {
        let returnData = {};
        // if (phone.length < 11 || phone.length > 13) {
        //     returnData = {
        //         code: 0,
        //         msg: this.ctx.__('checkPNError')
        //     }
        //     return returnData;
        // }
        console.log(phone) 
        console.log(msgType) 
        console.log(msgCode)
        //缓存中查询该手机号相关信息数据
        const findInfo = await this.ctx.model.SmsSendRecord.findOne({
            attributes: ['ID', 'SendTime', 'SendContent'],
            where: {
                Tel: phone,
                MsgType: msgType,
                IsEffect: true
            },
            order: [
                ['SendTime', 'DESC']
            ]
        })
        if (!findInfo) {
            returnData = {
                code: 0,
                checkOk: false,
                msg:  this.ctx.__('codeCheckEror')   
            }
            return returnData;
        }
        const { dataValues: { ID, SendTime, SendContent } } = findInfo
        if (msgCode != SendContent) {
            returnData = {
                code: 0,
                checkOk: false,
                msg: this.ctx.__('matchCodeError')
            }
            return returnData;
        }
        let lastDate = this.ctx.helper.dateAdd('m', this.app.config.aliSMS.expire, new Date(SendTime));
	lastDate = this.ctx.helper.dateAdd('h', 8 , new Date(lastDate));
	let currentDate = this.ctx.helper.dateAdd('h', 7 , new Date());
        currentDate = this.ctx.helper.dateAdd('m', -30 , currentDate );
	//console.log(lastDate)
	//console.log(currentDate)
        if (currentDate >= lastDate) {
            returnData = {
                code: 0,
                checkOk: false,
                msg: this.ctx.__('codeTimeout')  
            }
            return returnData;
        }
        returnData = {
            code: 1,
            checkOk: true,
            msg: this.ctx.__('checkOk') 
        }
        await this.ctx.model.SmsSendRecord.update({
            IsEffect: false
        }, {
            where: {
                ID: ID
            }
        });
        return returnData;
    }

    /**
     * 模拟发送短信验证码
     * @param {*} phone  手机号码
     * @param {*} randomCode 短信验证码
     * @param {*} listSendTime  历史发送信息
     * @param {*} templateCode 短信模板
     * @param {*} msgType 短信类型
     */
    async devCode(phone, randomCode, listSendTime, templateCode, msgType) {
        let returnData = {};
        let transaction;
        try {
            // 建立事务对象
            transaction = await this.ctx.model.transaction();

            let smsSendRecordItem = {
                ID: this.ctx.helper.getRandomNumber(9),
                RequestId: "ret.RequestId",
                BizId: "ret.BizId",
                ResultCode: "ret.Code",
                SendContent: randomCode,
                TemplateCode: templateCode,
                Tel: phone,
                SendTime: new Date(),
                MsgType: msgType,
                IsEffect: true
            }
            if (listSendTime != null && listSendTime != undefined && listSendTime.length > 0) {
                await this.ctx.model.SmsSendRecord.update({
                    IsEffect: false
                }, {
                    where: {
                        ID: listSendTime[0].ID
                    },
                    transaction
                });
            }
            await this.ctx.model.SmsSendRecord.create(smsSendRecordItem, {
                transaction
            });

            // 提交事务
            await transaction.commit();

            returnData = {
                code: 1,
                msg: '模拟发送验证码成功,请注意查收!!',
                msgCode: randomCode
            }
        } catch (err) {
            console.log(err)
            // 事务回滚
            await transaction.rollback();
            returnData = {
                code: 0,
                msg: '发验证码失败,请您重试!!'
            }
        }
        return returnData;
    }

    /**
     * 创建客户代码
     */
    async createCode() {
        let code = 'YD000000001';
        try {
            const findInfo = await this.ctx.model.CreateCodeRecord.findOne({
                attributes: ['OrderBy', 'CustomerCode'],
                order: [
                    ['OrderBy', 'DESC']
                ]
            })
            //查询到相关数据
            let orderBy = 1;//创建客户代码的数值
            if (findInfo) {
                const { dataValues: { OrderBy, CustomerCode } } = findInfo;
                orderBy = OrderBy + 1;
                //计算补零 0000 0000 1
                let numberCount = 9 - orderBy.toString().length;
                let zeroTxt = '';
                for (let k = 0; k < numberCount; k++) {
                    zeroTxt += '0';
                }
                code = 'YD' + zeroTxt + orderBy;
            }
            let createCodeItem = {
                ID: this.ctx.helper.getGuid16(),
                CustomerCode: code,
                OrderBy: orderBy,
                CreateTime: new Date(),
                ExtendField1: '',
                ExtendField2: '',
                ExtendField3: '',
            }

            await this.ctx.model.CreateCodeRecord.create(createCodeItem).then(result => {
                // console.log(result)
                //数据插入成功
            }).catch(err => {
                code = "";
            });
        } catch (err) {
            console.log(err);
            code = "";
        }
        return code;
    }

    /**
     * 字符串转base64
     * @param {*} str  待转换字符串
     */
    async strToBase64(str) {
        let base64 = '';
        base64 = new Buffer(str).toString('base64');
        base64 = base64.replace(/\+/g, '|');
        return base64;
    }

    /**
    * base64转字符串
    * @param {*} str  待转换字符串
    */
    async base642Str(base64) {
        let str = '';
        str = new Buffer(base64, 'base64').toString();
        str = str.replace(/\|/g, '+');
        return str;
    }

}


module.exports = UnitsService;
